#include <iostream>
#include <string>
#include <pthread.h>
#include <unistd.h>

//在创建多线程时，要在编译时加上-lpthread选项
//连接原生线程库，将库映射到地址空间之中
//linux中只有轻量级进程，cpu调度的时候看的是lwp（light weight process），使用ps -aL查看
//用户层面只任线程不认轻量级进程，所以在操作系统和用户层之间添加了一个pthread库，封装了
//创建线程的接口。所以Linux的线程实现，实在用户层实现的，我们称之为用户级线程，pthread
//就是原生线程库，虽然在用户层，但是和操作系统强绑定。
//所以我们写代码编译的时候要带着库。
//C++的多线程库，本质上是封装了pthread库
//在Windows下，封装的是Windows创建线程的接口
//为了保证语言的跨平台和可移植性：所有平台全都写一份，然后条件编译形成库

//线程的概念是在库内部维护的，会为你创建一个struct tcb，里面填充了线程栈大小、线程ID等
//线程相关信息以对线程进行处理
//在内存当中，在共享区里，
//在动态库当中有各个tid：tcb、线程局部存储、线程栈；可以认为下面还有其他的tid
//我们拿到的tid实际上就是线程在库中，对应的管理块的虚拟地址
//在tcb当中，存在一个void* ret，里面存放着线程的推出结果，所以说我们需要pthread_join
//来回收这个空间，tid是为了找到这个空间，传的&ret是为了取出退出结果把他放在这里面
//（我们传nullptr是因为我们默认这个线程没有异常）

//那tid是怎么和lwp进行联动的呢？
//在库中，我们会创建相应的空间以存储线程的控制块，在内核中，我们需要创建轻量级进程
//clone用来创建子线程，其中需要传入线程入口函数，需要传入tid中的栈区，
//栈区之上还有临时数据区用来存放产生的临时数据
//用户方法和用户栈结构，线程的相关结构和信息都被保存在内存的动态库中
//这些线程都在共享区的原生线程库当中，内核使用的是轻量级进程，在用户看来，就是线程
//在Linux下，用户级线程：内核LWP = 1 ： 1
//所以线程之间独立的资源就有各自的栈空间，能够供cpu独立调度

//Linux下的所有线程，信息、栈结构、状态等等都在我们物理内存中拷贝来的原生线程库中
//原则上，每个线程都能看到彼此的栈，但是地址互不知道所以访问不到

void* thread_function(void* arg)
{
    std::string name = (char*)arg;
    while(1)
    {
        std::cout << "我是一个子线程:" << name  << "pid:" << getpid()<< std::endl;
        sleep(1);
        // int a = 10; 
        // a /= 0;
    }
    return nullptr;
}

int main()
{
    pthread_t tid;
    pthread_create(&tid, nullptr, thread_function, (void*)"thread_1");
//                线程ID  线程属性   新线程要执行的函数入口      

    //主线程要等待子线程，否则会出现类似于僵尸进程的情况join
    while(1)
    {
        std::cout << "我是一个父线程" << "pid:" << getpid() << std::endl;
        sleep(1);
    }
    return 0;
}